﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

using MvcCms.Service.Cache;
using MvcCms.Service;
using MvcCms.Data;

using MvcCmsProjectTracker.Service;
using MvcCmsProjectTracker.ViewModels;
using System.Net.Mail;
using System.IO;
using System.Web.Security;

namespace MvcCmsProjectTracker.Controllers
{
    public class TicketController : MvcCms.Service.Code.BaseClasses.CMSControllerBase
    {
        #region Constructors     
        private readonly ICacheService _cacheService;
        private readonly IAccountService _accountService;
        private readonly ITicketService _ticketService;
        private readonly IProjectService _projectService;
        public TicketController(ICacheService cacheService, IAccountService accountService, IProjectService projectService, ITicketService ticketService, ICmsService cmsService, IZoneService zoneService)
            : base(cmsService, zoneService, accountService)
        {
            _cacheService = cacheService;
            _accountService = accountService;
            _ticketService = ticketService;
            _projectService = projectService;
        }
        #endregion

        [Authorize]
        public ActionResult MyHelpDesk()
        {
            var user = _accountService.GetUser();
            var results = new MyHelpDeskViewModel();
            results._HelpDeskProjectID = _projectService.GetHelpDeskProjects().FirstOrDefault().ProjectID;

            results._MyTickets = _ticketService.GetMyTickets(user.UserID).ToList();

            var helpPagesToShow = new List<HelpPage>();
            var helpPages = _projectService.GetHelpPages().ToList();
            foreach (var page in helpPages)
            {
                if (!string.IsNullOrEmpty(page.RolesCanView))
                {
                    var roles = page.RolesCanView.Split(',');
                    foreach (var role in roles)
                    {
                        if (Roles.IsUserInRole(role))
                        {
                            helpPagesToShow.Add(page);
                        }
                    }
                }
                else
                {
                    helpPagesToShow.Add(page);
                }
            }
            if (Roles.IsUserInRole("Admin") || Roles.IsUserInRole("HelpDeskAdmin")) { helpPagesToShow = helpPages; }
            results._HelpPages = helpPagesToShow;

            var ticketsToShow = new List<Ticket>();
            var openTickets = _ticketService.GetOpenHelpDeskTickets().ToList();
            foreach (var ticket in openTickets)
            {
                if (!string.IsNullOrEmpty(ticket.RolesCanView))
                {
                    var roles = ticket.RolesCanView.Split(',');
                    foreach (var role in roles)
                    {
                        if (Roles.IsUserInRole(role))
                        {
                            if (ticket.CreatorUserID != user.UserID)
                            {
                                ticketsToShow.Add(ticket);
                            }
                        }
                    }
                }
            }
            if (Roles.IsUserInRole("Admin") || Roles.IsUserInRole("HelpDeskAdmin")) { ticketsToShow = openTickets; }
            results._TicketsICanView = ticketsToShow;

            ViewBag.Title = "Help Desk";
            return View("MyHelpDesk", "_HelpDesk", results);
        }

        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public ActionResult Index()
        {                   
            var results = new TicketIndexViewModel();
            results.UsersProjects = _projectService.GetHelpDeskProjects().ToList();
            int projectId = 0;
            if (results.UsersProjects.Count()>0)
            {
                projectId = results.UsersProjects.FirstOrDefault().ProjectID;
                results.ActiveProjectID = projectId;
            }
            
            results.Tickets = _ticketService.GetTicketsByProject(projectId).ToList();

            ViewBag.Title = "Manage Tickets";
            return View(results);
        }

        [HttpPost]
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public ActionResult Index(int? projectID, FormCollection collection)
        {
            try
            {
                var results = new TicketIndexViewModel();
                results.UsersProjects = _projectService.GetHelpDeskProjects().ToList();
                results.ActiveProjectID = int.Parse(collection["ActiveProjectID"]);

                return RedirectToAction("Index", "Ticket", new
                {
                    projectID = collection["ActiveProjectID"]
                });
            }
            catch
            {
                return RedirectToAction("Index");
            }
        }

        [Authorize]
        public ActionResult Create(int projectid)
        {
            var results = new TicketCreateViewModel();
            var user = _accountService.GetUser();
            var project = _projectService.GetProject(projectid);
            if(project != null)
            {
                results.ProjectName = project.Name;
                results.Ticket = new Ticket()
                {
                    ProjectID = projectid,
                    AssignedTo = user
                };
            }
            if (Roles.IsUserInRole("Admin") || Roles.IsUserInRole("HelpDeskAdmin"))
            {
                results._CurrentAdminUserID = user.UserID;
                results._AllUsers = _accountService.ListUsers4Ajax().OrderBy(u=>u.UserName);
            }
            results.ProjectMilestones = _projectService.GetProjectMilestones(projectid).ToList();
            results.ProjectCategories = _projectService.GetProjectCategories(projectid).ToList();
            results.ProjectPriorities = _projectService.GetProjectPriorities(projectid).ToList();
            results.ProjectStatuses = _projectService.GetProjectStatuses(projectid).ToList();
            results.ProjectMembers = _projectService.GetProjectMembers(projectid).ToList();

            if(results.ProjectPriorities.Count > 0)
                results.Ticket.PriorityID = results.ProjectPriorities[0].PriorityID;
            if(results.ProjectStatuses.Count > 0)
                results.Ticket.StatusID = results.ProjectStatuses[0].StatusID;
            ViewBag.Title = "Create Ticket";
            return View("Create", "_HelpDesk", results);
        }

        [HttpPost]
        [Authorize]
        [ValidateInput(false)]
        public ActionResult Create(Ticket ticket)
        {
            var user = _accountService.GetUser();
            var saved = false;
            if(ModelState.IsValid)
            {
                if (!(Roles.IsUserInRole("Admin") || Roles.IsUserInRole("HelpDeskAdmin")))
                {                    
                    ticket.CreatedBy = user;
                }
                ticket.DateCreated = DateTime.Now;
                ticket.LastUpdate = DateTime.Now;                

                saved = _ticketService.CreateTicket(ticket);
                                
                if (saved)
                {
                    MvcCms.Service.Code.Email.MvcCmsEmails.DynamicEmail("New Ticket", _cacheService.GetCurrentPortal().AdminEmail, _cacheService.GetCurrentPortal().AdminEmail, "There is a new ticket to be processed from " + user.UserName);
                    if (Roles.IsUserInRole("Admin") || Roles.IsUserInRole("HelpDeskAdmin"))
                    {
                        return RedirectToAction("Index");
                    }
                    else
                    {
                        return RedirectToAction("MyHelpDesk");
                    }

                }
                else
                {
                    var results = new TicketCreateViewModel();
                    results.Message = "There was a problem";
                    results.Ticket = ticket;
                    var project = _projectService.GetProject(ticket.ProjectID);
                    if(project != null)
                    {
                        results.ProjectName = project.Name;
                    }

                    results.ProjectMilestones = _projectService.GetProjectMilestones(ticket.ProjectID).ToList();
                    results.ProjectCategories = _projectService.GetProjectCategories(ticket.ProjectID).ToList();
                    results.ProjectPriorities = _projectService.GetProjectPriorities(ticket.ProjectID).ToList();
                    results.ProjectStatuses = _projectService.GetProjectStatuses(ticket.ProjectID).ToList();
                    results.ProjectMembers = _projectService.GetProjectMembers(ticket.ProjectID).ToList();

                    if(results.ProjectPriorities.Count > 0)
                        results.Ticket.PriorityID = results.ProjectPriorities[0].PriorityID;
                    if(results.ProjectStatuses.Count > 0)
                        results.Ticket.StatusID = results.ProjectStatuses[0].StatusID;                    
                    return View(results);
                }
            }
            else
            {
                var results = new TicketCreateViewModel();
                results.Ticket = ticket;
                var project = _projectService.GetProject(ticket.ProjectID);
                if(project != null)
                {
                    results.ProjectName = project.Name;
                }
                if (Roles.IsUserInRole("Admin") || Roles.IsUserInRole("HelpDeskAdmin"))
                {
                    results._CurrentAdminUserID = user.UserID;
                    results._AllUsers = _accountService.ListUsers4Ajax().OrderBy(u => u.UserName);
                }
                results.ProjectMilestones = _projectService.GetProjectMilestones(ticket.ProjectID).ToList();
                results.ProjectCategories = _projectService.GetProjectCategories(ticket.ProjectID).ToList();
                results.ProjectPriorities = _projectService.GetProjectPriorities(ticket.ProjectID).ToList();
                results.ProjectStatuses = _projectService.GetProjectStatuses(ticket.ProjectID).ToList();
                results.ProjectMembers = _projectService.GetProjectMembers(ticket.ProjectID).ToList();

                if(results.ProjectPriorities.Count > 0)
                    results.Ticket.PriorityID = results.ProjectPriorities[0].PriorityID;
                if(results.ProjectStatuses.Count > 0)
                    results.Ticket.StatusID = results.ProjectStatuses[0].StatusID;
                ViewBag.Title = "Create Ticket";
                return View(results);
            }
        }

        // GET: /Ticket/Edit/5
        [Authorize]
        public ActionResult View(int id)
        {
            var results = new TicketEditViewModel();
            var user = _accountService.GetUser();
            results.Ticket = _ticketService.GetTicket(id);

            var project = _projectService.GetProject(results.Ticket.ProjectID);

            results.ActiveProjectID = project.ProjectID;

            if (project != null)
            {
                results.ProjectName = project.Name;
            }

            results.ProjectMilestones = _projectService.GetProjectMilestones(results.Ticket.ProjectID).ToList();
            results.ProjectCategories = _projectService.GetProjectCategories(results.Ticket.ProjectID).ToList();
            results.ProjectPriorities = _projectService.GetProjectPriorities(results.Ticket.ProjectID).ToList();
            results.ProjectStatuses = _projectService.GetProjectStatuses(results.Ticket.ProjectID).ToList();
            results.ProjectMembers = _projectService.GetProjectMembers(results.Ticket.ProjectID).ToList();

            results.TicketCommentViewModel = new TicketCommentViewModel()
            {
                TicketID = results.Ticket.TicketID,
                TicketComments = _ticketService.GetTicketComments(results.Ticket.TicketID).ToList()
            };
            results.TicketHistoryViewModel = new TicketHistoryViewModel()
            {
                TicketID = results.Ticket.TicketID,
                TicketHistory = _ticketService.GetTicketHistories(results.Ticket.TicketID).ToList()
            };

            results.TicketNotificationViewModel = new TicketNotificationViewModel()
            {
                TicketID = results.Ticket.TicketID,
                TicketNotifications = _ticketService.GetTicketNotifications(results.Ticket.TicketID).ToList()
            };

            results.TicketAttachmentViewModel = new TicketAttachmentsViewModel()
            {
                TicketID = results.Ticket.TicketID,
                TicketAttachments = _ticketService.GetTicketAttachments(results.Ticket.TicketID).ToList()
            };
            ViewBag.Title = "View Ticket";
            return View("View", "_HelpDesk", results);
        }

        // GET: /Ticket/Edit/5
        [Authorize]
        public ActionResult Edit(int id)
        {
            var results = new TicketEditViewModel();
            var user = _accountService.GetUser();
            results.Ticket = _ticketService.GetTicket(id);

            if (!(Roles.IsUserInRole("Admin") || Roles.IsUserInRole("HelpDeskAdmin")))
            {
                if (results.Ticket.CreatedBy.UserID != user.UserID)
                {
                    return Redirect("http://www.darwinawards.com");
                }
            }
            var project = _projectService.GetProject(results.Ticket.ProjectID);

            results.ActiveProjectID = project.ProjectID;

            if(project != null)
            {
                results.ProjectName = project.Name;
            }

            results.ProjectMilestones = _projectService.GetProjectMilestones(results.Ticket.ProjectID).ToList();
            results.ProjectCategories = _projectService.GetProjectCategories(results.Ticket.ProjectID).ToList();
            results.ProjectPriorities = _projectService.GetProjectPriorities(results.Ticket.ProjectID).ToList();
            results.ProjectStatuses = _projectService.GetProjectStatuses(results.Ticket.ProjectID).ToList();
            results.ProjectMembers = _projectService.GetProjectMembers(results.Ticket.ProjectID).ToList();

            results.TicketCommentViewModel = new TicketCommentViewModel()
            {
                TicketID = results.Ticket.TicketID,
                TicketComments = _ticketService.GetTicketComments(results.Ticket.TicketID).ToList()
            };
            results.TicketHistoryViewModel = new TicketHistoryViewModel()
            {
                TicketID = results.Ticket.TicketID,
                TicketHistory = _ticketService.GetTicketHistories(results.Ticket.TicketID).ToList()
            };

            results.TicketNotificationViewModel = new TicketNotificationViewModel()
            {
                TicketID = results.Ticket.TicketID,
                TicketNotifications = _ticketService.GetTicketNotifications(results.Ticket.TicketID).ToList()
            };

            results.TicketAttachmentViewModel = new TicketAttachmentsViewModel()
            {
                TicketID = results.Ticket.TicketID,
                TicketAttachments = _ticketService.GetTicketAttachments(results.Ticket.TicketID).ToList()
            };
            ViewBag.Title = "Edit Ticket";
            return View("Edit", "_HelpDesk", results);
        }

        // POST: /Ticket/Edit/5
        [HttpPost]
        [Authorize]
        [ValidateInput(false)]
        public ActionResult Edit(int id, Ticket editedTicket)
        {
            if(ModelState.IsValid)
            {
                try
                {
                    var user = _accountService.GetUser();
                    Ticket ticket = _ticketService.GetTicket(id);

                    List<object[]> changes = new List<object[]>();
                    object oldValue;

                    if(editedTicket.PriorityID != null)
                    {
                        oldValue = ticket.PriorityID ?? 0;
                        ticket.PriorityID = editedTicket.PriorityID;
                        changes.Add(new object[] { "Priority", oldValue, ticket.PriorityID });
                    }

                    if(editedTicket.StatusID != null)
                    {
                        oldValue = ticket.StatusID ?? 0;
                        ticket.StatusID = editedTicket.StatusID;
                        changes.Add(new object[] { "Status", oldValue, ticket.StatusID });
                    }

                    if ((Roles.IsUserInRole("Admin") || Roles.IsUserInRole("HelpDeskAdmin")))
                    {
                        if (editedTicket.AssignedUserID.HasValue)
                        {
                            oldValue = "None";
                            if (ticket.AssignedUserID.HasValue)
                            {
                                var previousAssignedTo = _accountService.GetUser(ticket.AssignedUserID.GetValueOrDefault());
                                oldValue = previousAssignedTo.UserName;
                            }
                            ticket.AssignedUserID = editedTicket.AssignedUserID;
                            var userAssignedTo = _accountService.GetUser(editedTicket.AssignedUserID.GetValueOrDefault());
                            changes.Add(new object[] { "Assigned To", oldValue, userAssignedTo.UserName });
                        }
                    }

                    oldValue = ticket.Description ?? "";
                    ticket.Description = editedTicket.Description;
                    changes.Add(new object[] { "Description", oldValue, ticket.Description });

                    oldValue = ticket.Title ?? "";
                    ticket.Title = editedTicket.Title;
                    changes.Add(new object[] { "Title", oldValue, ticket.Title });

                    oldValue = ticket.LastUpdate;
                    ticket.LastUpdate = DateTime.Now;
                    changes.Add(new object[] { "Last Update", oldValue, ticket.LastUpdate });

                    TicketHistory newHistory = new TicketHistory()
                    {
                        TicketID = ticket.TicketID,
                        Changes = ticket.GetTicketChanges(changes),
                        UserName = User.Identity.Name,
                        DateCreated = DateTime.Now
                    };
                    ticket.Histories.Add(newHistory);

                    if ((Roles.IsUserInRole("Admin") || Roles.IsUserInRole("HelpDeskAdmin")))
                    {
                        ticket.RolesCanView = editedTicket.RolesCanView;
                        ticket.Closed = editedTicket.Closed;
                    }

                    _ticketService.EditTicket(ticket);

                    //Send out email notifications
                    foreach (TicketNotification notification in _ticketService.GetTicketNotifications(id))
                    {                        
                        MailAddress fromAddress = new MailAddress(_cacheService.GetCurrentPortal().AdminEmail);
                        string subject = string.Format("Ticket {0} has been modified by {1}", id, User.Identity.Name);
                        string body = newHistory.Changes;
                        MailMessage message = new MailMessage()
                        {
                            From = fromAddress,
                            Subject = subject,
                            Body = body,
                            IsBodyHtml = true
                        };
                        MvcCms.Service.Code.Email.MvcCmsEmails.SendMessage(user.Email, message);
                    }
                    if (Roles.IsUserInRole("Admin") || Roles.IsUserInRole("HelpDeskAdmin"))
                    {
                        return RedirectToAction("Index");
                    }
                    else
                    {
                        return RedirectToAction("MyHelpDesk");
                    }
                }
                catch
                {
                    ViewBag.Title = "Edit Ticket";
                    return View();
                }
            }
            else
            {
                return RedirectToAction("Edit", id);
            }

        }

        // GET: /Ticket/Delete/5
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public ActionResult Delete(int id)
        {
            try
            {
                Ticket ticket = _ticketService.GetTicket(id);

                return View(ticket);
            }
            catch
            {
                return View();
            }
        }

        // POST: /Bug/Delete/5
        [HttpPost]
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public ActionResult Delete(int id, FormCollection collection)
        {
            try
            {
                var ticket = _ticketService.GetTicket(id);
                _ticketService.DeleteTicket(ticket);
                _ticketService.Save();
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

        // AJAX: /Ticket/DeleteComment/2
        [HttpPost]
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public PartialViewResult DeleteComment(int id)
        {
            TicketComment comment = _ticketService.GetTicketComment(id);
            int ticketID = comment.TicketID;
            _ticketService.DeleteTicketComment(comment);
            _ticketService.Save();
            var results = new TicketCommentViewModel
            {
                Message = "Comment has been removed from the ticket.",
                TicketID = ticketID,
                TicketComments = _ticketService.GetTicketComments(ticketID).ToList()
            };

            return PartialView("TicketComments", results);
        }

        // AJAX: /Ticket/AddComment/2
        [HttpPost]
        [Authorize]
        [ValidateInput(false)]
        public PartialViewResult AddComment(int id, FormCollection collection)
        {
            TicketComment comment = new TicketComment();
            comment.TicketID = id;
            comment.Comment = collection["comment"];
            comment.DateCreated = DateTime.Now;
            comment.UserName = User.Identity.Name;

            _ticketService.AddTicketComment(comment);
            _ticketService.Save();
            var results = new TicketCommentViewModel
            {
                Message = "Comment has been added to the ticket.",
                TicketID = comment.TicketID,
                TicketComments = _ticketService.GetTicketComments(comment.TicketID).ToList()
            };

            return PartialView("TicketComments", results);
        }

        // POST: /Ticket/Delete/5
        [HttpPost]
        [Authorize]
        public ActionResult DeleteNotification(int id)
        {
            TicketNotification notification = _ticketService.GetTicketNotification(id);
            int ticketID = notification.TicketID;
            _ticketService.DeleteTicketNotification(notification);

            _ticketService.Save();
            var results = new TicketNotificationViewModel
            {
                Message = "Notification has been deleted from the ticket.",
                TicketID = ticketID,
                TicketNotifications = _ticketService.GetTicketNotifications(ticketID).ToList()
            };

            return PartialView("TicketNotifications", results);
        }

        // AJAX: /Ticket/AddNotification/2
        [HttpPost]
        [Authorize]
        public PartialViewResult AddNotification(int id)
        {
            TicketNotification notification = new TicketNotification();
            notification.TicketID = id;
            notification.UserName = User.Identity.Name;

            _ticketService.AddTicketNotification(notification);
            _ticketService.Save();
            var results = new TicketNotificationViewModel
            {
                Message = "Notification has been added to the ticket.",
                TicketID = notification.TicketID,
                TicketNotifications = _ticketService.GetTicketNotifications(notification.TicketID).ToList()
            };

            return PartialView("TicketNotifications", results);
        }

        [HttpPost]
        [Authorize]
        public ActionResult AddAttachment(int id, FormCollection collection)
        {
            TicketAttachment attachment = new TicketAttachment();
            attachment.TicketID = id;
            attachment.UserName = User.Identity.Name;
            attachment.ContentType = Request.Files["file"].ContentType;

            Stream fileStream = Request.Files["file"].InputStream;
            attachment.FileName = Path.GetFileName(Request.Files["file"].FileName);
            int fileLength = Request.Files["file"].ContentLength;
            byte[] fileData = new byte[fileLength];
            fileStream.Read(fileData, 0, fileLength);
            attachment.Attachment = fileData;

            _ticketService.AddTicketAttachment(attachment);
            _ticketService.Save();
            return RedirectToAction("Edit", "Ticket", new
            {
                id = id
            });
        }

        [HttpPost]
        [Authorize(Roles = "Admin, HelpDeskAdmin")]
        public PartialViewResult DeleteAttachment(int id)
        {
            TicketAttachment attachment = _ticketService.GetTicketAttachment(id);
            int ticketID = attachment.TicketID;
            _ticketService.DeleteTicketAttachment(attachment);
            _ticketService.Save();
            var results = new TicketAttachmentsViewModel
            {
                Message = "Attachment has been deleted from the ticket.",
                TicketID = ticketID,
                TicketAttachments = _ticketService.GetTicketAttachments(ticketID).ToList()
            };

            return PartialView("TicketAttachments", results);
        }

        [Authorize]
        public FileContentResult GetAttachment(int id)
        {
            TicketAttachment attachment = _ticketService.GetTicketAttachment(id);

            return File(attachment.Attachment, attachment.ContentType, attachment.FileName);

        }
     
    }
}
